<?php

// $Id$

require_once(TANGRA_MAIN_DIR.'interfaces/i_db_storable.class.php');
require_once('tree_menu_item.class.php');


class Tree_Menu_Item_DBC extends Tree_Menu_Item implements I_DB_Storable {
	private $table;

	function __construct($table = 'menu') {
		$this->set_table($table);
	}


	public function set_table($table) {
		$this->table = $table;
	}


	public function get_table() {
		return $this->table;
	}


	public function save(DB_Connection $dbc) {
		$ret = false;

		if ($this->get_id()) {
			$ret = $this->update($dbc);
		} else {
			$ret = $this->insert($dbc);
			$this->set_id($ret);
		}

		if ($ret) {
			$items = $this->get_subitems();
			foreach($items as $item) {
				$item->set_parent($ret);
				$item->save($dbc);
			}
		}


		return $ret;
	}


	public function load_by_id(DB_Connection $dbc, $id) {
		tangra_if_not_int_throw_e($id);

		$ret = $this->_load_by_id($dbc, $id);
		$table = addslashes($this->get_table());

		if ($ret) {
			$sql = "select id from $table where parent = $id order by `order` asc";
			$rez = $dbc->execute($sql);
			while($rez_obj = $rez->fetch_object()) {
				$item = new Tree_Menu_Item_DBC($table);
				$item->load_by_id($dbc, $rez_obj->ID);

				$this->add_subitem(clone $item);
			}
		}


		return $ret;
	}


	protected function _load_by_id(DB_Connection $dbc, $id) {
		$ret = false;
		$table = addslashes($this->get_table());

		$sql = "select label, "
						." parent,"
						." link,"
						." hid,"
						." target,"
						." `order`"
					." from $table "
					."where id = $id";
		$rez = $dbc->execute($sql);

		if (!$rez->is_eof()) {
			$rez_obj = $rez->fetch_object();

			$this->set_id($id);
			$this->set_label(stripslashes($rez_obj->LABEL));
			$this->set_parent($rez_obj->PARENT);
			$this->set_link(stripslashes($rez_obj->LINK));
			$this->set_hid(stripslashes($rez_obj->HID));
			$this->set_target(stripslashes($rez_obj->TARGET));
			$this->set_order($rez_obj->ORDER);

			$ret = $id;
		}

		return $ret;
	}


	protected function insert(DB_Connection $dbc) {
		$ret = false;

		$table = addslashes($this->get_table());
		$id = $dbc->generate_id($table.'_seq');

		$label = addslashes($this->get_label());
		$parent = $this->get_parent();
		$link = addslashes($this->get_link());
		$hid = addslashes($this->get_hid());
		$target = addslashes($this->get_target());
		$order = $this->get_order();

		if ($id) {
			$sql = "insert into $table (id, "
											."label, "
											."parent, "
											."link, "
											."hid, "
											."target, "
											."`order` "
									      .") ".
								"values ".
									      "($id,".
									      "'$label', ".
									      "$parent, ".
									      "'$link', ".
									      "'$hid', ".
									      "'$target', ".
									      "$order ".
									      ")";
			$dbc->execute($sql);
			$ret = $id;
		} else {
			throw new TE_Exception('ID not generated - '.$table.'_seq');
		}


		return $ret;
	}


	protected function update(DB_Connection $dbc) {
		$id = $this->get_id();

		$table = addslashes($this->get_table());

		$label = addslashes($this->get_label());
		$parent = $this->get_parent();
		$link = addslashes($this->get_link());
		$hid = addslashes($this->get_hid());
		$target = addslashes($this->get_target());
		$order = $this->get_order();


		$sql = "update $table set ".
							      "label = '$label', ".
							      "parent = $parent, ".
							      "link = '$link', ".
							      "hid = '$hid', ".
							      "target = '$target', ".
							      "`order` = $order ".
					"where id = ".$id;

		$dbc->execute($sql);
		$ret = $id;


		return $ret;
	}


	public function add_subitem(Tree_Menu_Item $item) {
		if ($item instanceof Tree_Menu_Item_DBC) {
			parent::add_subitem($item);
		} else {
			throw new TE_Tree_Menu('$item is not instance of Tree_Menu_Item_DBC');
		}
	}


	public function update_subitem(Tree_Menu_Item_DBC $item) {
		if ($this->subitem_exists($item)) {

			$item_orig = $this->subitems[$item->get_hid()];
			$id = $item_orig->get_id();
			$subitems = $item_orig->get_subitems();

			$item->set_id($id);
			$item->set_subitems($subitems);
			$this->subitems[$item->get_hid()] = $item;
		} else {
			throw new TE_Tree_Menu('Such subitem does not exists: '.$item->get_label());
		}
	}


	public static function delete(DB_Connection $dbc, $id, $table = 'menu') {
		tangra_if_not_int_throw_e($id);

		$sql = "delete from $table where id = $id";

		$dbc->execute($sql);
	}


	public static function move_up(DB_Connection $dbc, $id, $table = '') {
		$table = addslashes($table);

		$current = new Tree_Menu_Item_DBC($table);

		if ($current->load_by_id($dbc, $id)) {
			$sql = "select id from $table where "
						."parent = ".$current->get_parent()
						." and `order` <= ".$current->get_order()
						." and id <> $id "
						." order by `order` desc";
			$rez = $dbc->execute($sql);
			if (!$rez->is_eod()) {
				$above = new Tree_Menu_Item_DBC($table);
				$rez_obj = $rez->fetch_object();
				$above->load_by_id($dbc, $rez_obj->ID);

				if ($current->get_order() != $above->get_order()) {
					// Swaping orders
					$tmp = $current->get_order();
					$current->set_order($above->get_order());
					$above->set_order($tmp);
				} else {
					if (($above->get_order() - 10) > 0) {
						$current->set_order($above->get_order() - 10);
					} else {
						$above->set_order($above->get_order() + 10);
					}
				}

				$current->save($dbc);
				$above->save($dbc);
			}
		}
	}


	public static function move_down(DB_Connection $dbc, $id, $table = '') {
		$table = addslashes($table);

		$current = new Tree_Menu_Item_DBC($table);

		if ($current->load_by_id($dbc, $id)) {
			$sql = "select id from $table where "
						."parent = ".$current->get_parent()
						." and `order` >= ".$current->get_order()
						." and id <> $id "
						." order by `order` asc";

			$rez = $dbc->execute($sql);
			if (!$rez->is_eod()) {
				$bellow = new Tree_Menu_Item_DBC($table);
				$rez_obj = $rez->fetch_object();
				$bellow->load_by_id($dbc, $rez_obj->ID);

				if ($current->get_order() != $bellow->get_order()) {
					// Swaping orders
					$tmp = $current->get_order();
					$current->set_order($bellow->get_order());
					$bellow->set_order($tmp);
				} else {
					$current->set_order($bellow->get_order() + 10);
				}

				$current->save($dbc);
				$bellow->save($dbc);
			}
		}
	}


	public static function is_unique_hid(DB_Connection $dbc, $hid, $table = '') {
		$hid = addslashes($hid);
		$table = addslashes($table);

		$sql = "select id from $table where hid = '$hid'";
		$rez = $dbc->execute($sql);

		return $rez->is_eod();
	}


	public static function is_unique_hid_update(DB_Connection $dbc, $hid, $id, $table = '') {
		tangra_if_not_int_throw_e($id);
		$hid = addslashes($hid);
		$table = addslashes($table);

		$sql = "select id from $table where hid = '$hid' and id <> $id";
		$rez = $dbc->execute($sql);

		return $rez->is_eod();
	}


	public static function get_next_order(DB_Connection $dbc, $parent_id, $prefix) {
		tangra_if_not_int_throw_e($parent_id);

		$ret = 10;

		$sql = "select `order` from ".$prefix."menu where parent = $parent_id order by `order` desc";
		$rez = $dbc->execute($sql);
		if (!$rez->is_eod()) {
			$rez_obj = $rez->fetch_object();
			$ret = ((int)($rez_obj->ORDER / 10) + 1)*10; //next ordering calculation
		}

		return $ret;
	}
}